home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / os2 / cenv2_19.arj / KEYPUSH.LIB < prev    next >
Text File  |  1994-03-08  |  16KB  |  431 lines

  1. // KeyPush.lib - PM routines to control, or mimic, the pushing of
  2. // ver.1         keys on the keyboard.  This is one method of controlling
  3. //               windows applications.  The functions in this library work
  4. //               by sending keyboard messages to the focus window as if
  5. //               the key messages were actually being sent by Windows.
  6. //
  7. //**** KeyPushFocusID(): Select focus window specification for this library
  8. // SYNTAX: int KeyPushFocusID(NULL)   // this is the default
  9. //         int KeyPushFocusID(string TopLevelTitle[,TempMakeActive])
  10. //         int KeyPushFocusID(int TopLevelHandle[,TempMakeActive])
  11. //         int KeyPushFocusID(int FocusWindowHandle)
  12. // WHERE: NULL: if NULL or 0 then will always send to the currently active focus window
  13. //        TopLevelTitle: ascii string - will send to focus window of this top-level window
  14. //        TopLevelHandle: handle for top-level window - will send to focus window of this top-level window
  15. //        FocusWindowHandle: will send directly to this window handle
  16. //        TempMakeActive: This window (or top-level window) for this application
  17. //                        must be the active window while the keystrokes are
  18. //                        sent, and will temporarily be made active.  The default
  19. //                        is TRUE for TopLevelTitle and TopLevelHandle methods, else
  20. //                        this doesn't apply and does not switch active window.
  21. // RETURN: Return window that would get focus NOW according to this setting, which
  22. //         may be NULL if this setting wouldn't work
  23. // NOTE: For TopLevelTitle and TopLevelHandle methods, these library routines
  24. //       may need to temporarily alter the activation of different windows if
  25. //       you don't specify TempMakeActive=False, which will look messy if the
  26. //       window you're sending to is not currently the active window.  In these
  27. //       situations, or if you're sending lots of KeyPushxxx messages, you may
  28. //       want to make the application active first or get the FocusWindowHandle
  29. //       if the window won't change.  For top level windows where this is not
  30. //       TempMakeActive is not given or is True, then will not make the application
  31. //       active but will only send to sub-window that last had active focus.
  32. //
  33. //
  34. //**** KeyStroke(): Press and release a key or combination of keys
  35. // SYNTAX: int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]byte Character)
  36. //         int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]int VirtualKeyCode)
  37. //         int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]string KeyString)
  38. // WHERE: Holdkey...: mimic that these keys are pressed before KeyCode or KeyString, and then
  39. //                    will press and release KeyCode or KeyString, and then will release
  40. //                    HoldKeys in reverse order.
  41. //        Character: ascii character to send
  42. //        VirtualKeyCode: one of the VK_ key codes (see below)
  43. //        KeyString: Ascii string to send
  44. // RETURN: Return handle keys were sent to; 0 if no handle found
  45. // EXAMPLES: To press the 'S' key: KeyStroke('S');
  46. //           To type a sentence: KeyStroke("On top of Old Smokey!\n");
  47. //           To type Alt-F1: KeyStroke("VK_ALT,VK_F1);
  48. //           To simulate Ctl-Alt-R: KeyStroke(VK_CONTROL,VK_ALT,'R');
  49. //
  50. //
  51. //**** SpeedKeys(): Send character messages
  52. // SYNTAX: int SpeedKeys(string AsciiString[,DelayBetweenKeys])
  53. //         int SpeedKeys(byte Character[,DelayBetweenKeys])
  54. // WHERE: AsciiString: string of characters to send
  55. //        Character: single character to send
  56. //        DelayBetweenKeys: Approximate time, in milliseconds, to wait after
  57. //                          sending each key message
  58. // NOTE: Speed keys sends only WM_CHAR messages to an application and is much
  59. //       faster than KeyStroke(), but should only be used for regular ascii
  60. //       strings passed to applications that don't need to for each specific
  61. //       keystroke.  So, if KeyStroke() is too slow and you're entering a
  62. //       stretch of plain text, then use this function.
  63. //
  64. //
  65. //**** VKeyDown(): Press down a key (no release yet)
  66. // SYNTAX: int VKeyDown(int KeyCode)
  67. // WHERE: KeyCode: Virtual VK_ key or character key
  68. // RETURN: Return handle keys were sent to; 0 if no handle found
  69. //
  70. //
  71. //**** VKeyUP(): Release a key (that has been pressed down)
  72. // SYNTAX: int VKeyUP(int KeyCode)
  73. // WHERE: KeyCode: Virtual VK_ key or character key
  74. // RETURN: Return handle keys were sent to; 0 if no handle found
  75. //
  76. //
  77.  
  78. #include <WinMsg.lib>
  79. #include <GiveMem.lib>
  80. #include <WinTools.lib>
  81.  
  82. /*** Virtual key values *************************************************/
  83. #define VK_BUTTON1   0x01
  84. #define VK_BUTTON2   0x02
  85. #define VK_BUTTON3   0x03
  86. #define VK_BREAK     0x04
  87. #define VK_BACKSPACE 0x05
  88. #define VK_TAB       0x06
  89. #define VK_BACKTAB   0x07
  90. #define VK_NEWLINE   0x08
  91. #define VK_SHIFT     0x09
  92. #define VK_CTRL      0x0A
  93. #define VK_ALT       0x0B
  94. #define VK_ALTGRAF   0x0C
  95. #define VK_PAUSE     0x0D
  96. #define VK_CAPSLOCK  0x0E
  97. #define VK_ESC       0x0F
  98. #define VK_SPACE     0x10
  99. #define VK_PAGEUP    0x11
  100. #define VK_PAGEDOWN  0x12
  101. #define VK_END       0x13
  102. #define VK_HOME      0x14
  103. #define VK_LEFT      0x15
  104. #define VK_UP        0x16
  105. #define VK_RIGHT     0x17
  106. #define VK_DOWN      0x18
  107. #define VK_PRINTSCRN 0x19
  108. #define VK_INSERT    0x1A
  109. #define VK_DELETE    0x1B
  110. #define VK_SCRLLOCK  0x1C
  111. #define VK_NUMLOCK   0x1D
  112. #define VK_ENTER     0x1E
  113. #define VK_SYSRQ     0x1F
  114. #define VK_F1        0x20
  115. #define VK_F2        0x21
  116. #define VK_F3        0x22
  117. #define VK_F4        0x23
  118. #define VK_F5        0x24
  119. #define VK_F6        0x25
  120. #define VK_F7        0x26
  121. #define VK_F8        0x27
  122. #define VK_F9        0x28
  123. #define VK_F10       0x29
  124. #define VK_F11       0x2A
  125. #define VK_F12       0x2B
  126. #define VK_F13       0x2C
  127. #define VK_F14       0x2D
  128. #define VK_F15       0x2E
  129. #define VK_F16       0x2F
  130. #define VK_F17       0x30
  131. #define VK_F18       0x31
  132. #define VK_F19       0x32
  133. #define VK_F20       0x33
  134. #define VK_F21       0x34
  135. #define VK_F22       0x35
  136. #define VK_F23       0x36
  137. #define VK_F24       0x37
  138. #define VK_ENDDRAG   0x38
  139. #define VK_MENU      VK_F10
  140.  
  141.  
  142. KeyPushFocusID(pFocusID,pTempMakeActive)
  143. {
  144.    gFocusIDIsTopLevel = False;
  145.    if ( !pFocusID ) {
  146.       gFocusID = 0;
  147.       gKPTempMakeActive = False;
  148.    } else if ( 0 != DataDimension(pFocusID) ) {
  149.       // find window based on string
  150.       if ( !(gFocusID = GetWindowHandle(pFocusID)) )
  151.          return 0;
  152.       gFocusIDIsTopLevel = True;
  153.    } else {
  154.       // determine if this is one of the top level windows
  155.       lEnum = WinBeginEnumWindows(HWND_DESKTOP);
  156.       while ( lChild = WinGetNextWindow(lEnum) ) {
  157.          if ( pFocusID == lChild ) {
  158.             gFocusIDIsTopLevel = True;
  159.             break;
  160.          }
  161.       }
  162.       WinEndEnumWindows(lEnum);
  163.       gFocusID = pFocusID;
  164.    }
  165.    gKPTempMakeActive = ( va_arg() < 2 ) ? True : pTempMakeActive ;
  166.  
  167.    // gFocusID parameter is set.  Return window handle as regular KeyPush calls would
  168.    KeyPushInitialize();
  169.    KeyPushTerminate();
  170.    return gKPFocusWindow;
  171. }
  172.  
  173.  
  174. KeyStroke(pKey1,pKey2,pKey3/*etc...*/)
  175. {
  176.    if ( KeyPushInitialize() ) {
  177.       lArgCount = va_arg();
  178.       // if more than one parameter, then hold down all but the last one
  179.       for ( lKeyC = 1; lKeyC < lArgCount; lKeyC++ )
  180.          KeyDown(va_arg(lKeyC-1));
  181.  
  182.       lKey = va_arg(lArgCount-1);
  183.       // Treat differently depending on whether Virtual Key Code, char, or string
  184.       if ( CMM_BYTE == DataType(lKey) ) {
  185.          if ( 1 == DataDimension(lKey) ) {
  186.             // send entire string one character at a time
  187.             for ( lIdx = 0; lKey[lIdx]; lIdx++ ) {
  188.                KeyDown(lKey[lIdx]);
  189.                KeyUp(lKey[lIdx]);
  190.             }
  191.          } else {
  192.             // send a single character out the port
  193.             KeyDown(lKey);
  194.             KeyUp(lKey);
  195.          }
  196.       } else {
  197.          // simply a virtual key code
  198.          KeyDown(lKey);
  199.          KeyUp(lKey);
  200.       }
  201.  
  202.       // if more than one parameter, then reverse release all but the last one
  203.       for ( lKeyC = 1; lKeyC < lArgCount; lKeyC++ )
  204.          KeyUp(va_arg(lArgCount-lKeyC-1));
  205.    }
  206.    KeyPushTerminate();
  207.    return gKPFocusWindow;
  208. }
  209.  
  210. #define WM_CHAR   0x007a
  211. #define WM_TRANSLATEACCEL 0x004b
  212.  
  213. /* WM_CHAR fs field bits */
  214. #define KC_CHAR         0x0001
  215. #define KC_VIRTUALKEY   0x0002
  216. #define KC_SCANCODE     0x0004
  217. #define KC_SHIFT        0x0008
  218. #define KC_CTRL         0x0010
  219. #define KC_ALT          0x0020
  220. #define KC_KEYUP        0x0040
  221. #define KC_PREVDOWN     0x0080
  222. #define KC_LONEKEY      0x0100
  223. #define KC_DEADKEY      0x0200
  224. #define KC_COMPOSITE    0x0400
  225. #define KC_INVALIDCOMP  0x0800
  226. #define KC_TOGGLE       0x1000
  227. #define KC_INVALIDCHAR  0x2000
  228. #define KC_DBCSRSRVD1   0x4000
  229. #define KC_DBCSRSRVD2   0x8000
  230.  
  231. gKPLatestKeyDown = FALSE; // True on call to key down, false on KeyUp
  232.  
  233. KeyDown(pKey)
  234. {
  235.    if ( KeyPushInitialize() ) {
  236.       // Save the current state of the 256-byte keyboard buffer
  237.       lKeyTable = GetKeyboardTable();
  238.  
  239.       gKPLatestKeyDown = TRUE;
  240.  
  241.       if ( CMM_BYTE == DataType(pKey) ) {
  242.          // pushing just a character
  243.          lfsflags = KC_CHAR;
  244.          lusch = pKey;
  245.          lusvk = 0;
  246.       } else {
  247.          // pushing a virtual key
  248.          lfsflags = KC_VIRTUALKEY;
  249.          lusch = 0;
  250.          lusvk = pKey;
  251.          if ((lKeyTable[pKey] = (lKeyTable[pKey] | 0x80) ^ 1) & 0x01)
  252.             lfsflags |= KC_TOGGLE;
  253.          SetKeyboardTable(lKeyTable);
  254.       }
  255.  
  256.       if ( lKeyTable[VK_SHIFT] & 0x80 )
  257.          lfsflags |= KC_SHIFT;
  258.       if ( lKeyTable[VK_ALT] & 0x80 )
  259.          lfsflags |= KC_ALT;
  260.       if ( lKeyTable[VK_CTRL] & 0x80 )
  261.          lfsflags |= KC_CTRL;
  262.  
  263.       SendMessageAndAccelTable(lfsflags | (1 << 16),lusch | (lusvk << 16));
  264.    }
  265.    KeyPushTerminate();
  266.    return gKPFocusWindow;
  267. }
  268.  
  269. KeyUp(pKey)
  270. {
  271.    if ( KeyPushInitialize() ) {
  272.       // Save the current state of the 256-byte keyboard buffer
  273.       lKeyTable = GetKeyboardTable();
  274.  
  275.       // set some fsflags based on keys currently pressed
  276.       lfsflags = KC_KEYUP /*| KC_PREVDOWN*/;
  277.  
  278.       if ( CMM_BYTE == DataType(pKey) ) {
  279.          // pushing just a character
  280.          lfsflags |= KC_CHAR;
  281.          if ( (lKeyTable[VK_CTRL] & 0x80)  &&  isalpha(pKey) )
  282.             // convert to control character
  283.             lusch = toupper(pKey) - 'A' + 1;
  284.          else
  285.             lusch = pKey;
  286.          lusvk = 0;
  287.       } else {
  288.          // pushing a virtual key
  289.          lfsflags |= KC_VIRTUALKEY;
  290.          lusch = 0;
  291.          lusvk = pKey;
  292.          if ((lKeyTable[pKey] &= 0x7F) & 0x01);
  293.             lfsflags |= KC_TOGGLE;
  294.          SetKeyboardTable(lKeyTable);
  295.       }
  296.  
  297.       if ( lKeyTable[VK_SHIFT] & 0x80 )
  298.          lfsflags |= KC_SHIFT;
  299.       if ( lKeyTable[VK_ALT] & 0x80 )
  300.          lfsflags |= KC_ALT;
  301.       if ( lKeyTable[VK_CTRL] & 0x80 )
  302.          lfsflags |= KC_CTRL;
  303.  
  304.       if ( gKPLatestKeyDown )
  305.          lfsflags |= KC_LONEKEY;
  306.       gKPLatestKeyDown = FALSE;
  307.  
  308.       // send message to window that this key is being pressed
  309.       SendMessageAndAccelTable(lfsflags | (1 << 16),lusch | (lusvk << 16));
  310.    }
  311.    KeyPushTerminate();
  312.    return gKPFocusWindow;
  313. }
  314.  
  315. SpeedKeys(pAsciiString,pDelayBetweenCharacters)
  316. {
  317.    if ( KeyPushInitialize() ) {
  318.       if ( 1 == DataDimension(pAsciiString) ) { lChar = pAsciiString; }
  319.       else { lChar[1] = '\0'; lChar[0] = pAsciiString; }
  320.       for ( ; lChar[0]; lChar++ ) {
  321.          lParam1 = ((KC_CHAR | KC_LONEKEY)) | (1 << 16);
  322.          WinSendMsg(gKPFocusWindow,WM_CHAR,lParam1,lChar[0]);
  323.          if ( 1 < va_arg() )
  324.             suspend(pDelayBetweenCharacters);
  325.       }
  326.    }
  327.    KeyPushTerminate();
  328.    return gKPFocusWindow;
  329. }
  330.  
  331.  
  332. /***********************************************************
  333.  *** PRIVATE UTILITIES USED BY THE ABOVE PUBLIC ROUTINES ***
  334.  ***********************************************************/
  335.  
  336. gFocusID = 0;
  337. gFocusIDIsTopLevel = False; // set true if using Focus ID that is top-level window
  338. gKeyPushInitializeDepth = 0;  // keep track how many times recursively called
  339. gKPFocusWindow;  // KeyPushInitialize sets to window
  340. gKPSaveActiveWindow = 0;
  341. gKPTempMakeActive = True;
  342.  
  343. KeyPushInitialize()
  344. {
  345.    // keep track of how many times called.  get actual ID to send to on first
  346.    // level, on recursive calls revert to first return.  If need to activate
  347.    // window then do so.  Return FALSE for failure, else non-false is TRUE
  348.    if ( 0 == gKeyPushInitializeDepth++ ) {
  349.       gKPSaveActiveWindow = 0; // assume don't need to change focus
  350.       if ( !gFocusID ) {
  351.          // take whatever is the focus window
  352.          gKPFocusWindow = GetFocus();
  353.       } else if ( !IsWindow(gFocusID) ) {
  354.          gKPFocusWindow = 0;  // gFocusID is not valid
  355.       } else if ( !gFocusIDIsTopLevel ) {
  356.          gKPFocusWindow = gFocusID; // this isn't top level, so is actual window to send to
  357.       } else {
  358.          // this is a top level window, if KeyPushFocusID() set up to make active
  359.          // when sending keystrokes then do so, else send to the child that was
  360.          // the focus when this window was active
  361.          if ( gFocusID == (lActive=GetActiveWindow()) ) {
  362.             gKPFocusWindow = GetFocus();
  363.          } else {
  364.             if ( gKPTempMakeActive ) {
  365.                gKPSaveActiveWindow = lActive;
  366.                SetActiveWindow(gFocusID);
  367.                gKPFocusWindow = GetFocus();
  368.             } else {
  369.                gKPFocusWindow = GetFocusChild(gFocusID);
  370.             }
  371.          }
  372.       }
  373.  
  374.    }
  375.    return gKPFocusWindow;
  376. }
  377.  
  378. KeyPushTerminate()
  379. {
  380.    // undo what KeyPushInitialize did. restore active window if KeyPushInitialize()
  381.    // activated it.  Must call same number of times as KeyPushInitialize.
  382.    if ( 0 == --gKeyPushInitializeDepth ) {
  383.       if ( gKPSaveActiveWindow ) {
  384.          SetActiveWindow(gKPSaveActiveWindow);
  385.       }
  386.    }
  387. }
  388.  
  389. #define HWND_DESKTOP    1
  390. #define ORD_WIN32SETKEYBOARDSTATETABLE   921
  391.  
  392. GetKeyboardTable()   // return 256 byte buffer for current keyboard state
  393. {
  394.    lTable[255] = '\0';   // initialize 256-byte key table
  395.    DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
  396.                HWND_DESKTOP,lTable,FALSE);
  397.    return(lTable);
  398. }
  399.  
  400. SetKeyboardTable(pKeyBuf)  // set the 256 byte buffer for current keyboard state
  401. {
  402.    DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
  403.                HWND_DESKTOP,pKeyBuf,TRUE);
  404. }
  405.  
  406.  
  407. /***********************************/
  408. /*** SEND KEY MESSAGES TO WINDOW ***/
  409.  
  410. SendMessageAndAccelTable(pParam1,pParam2)
  411.    // Send this message and send an accelerator table message
  412. {
  413.    // see that the current window has been given access to the shared
  414.    // memory table memory
  415.    lSharedMemory = GiveMemoryToWindow(gKPFocusWindow);
  416.  
  417.    // copy the message to the globally allocated and shared memory
  418.    // build blob message to give to accelerator table
  419.    poke( lSharedMemory, gKPFocusWindow, UWORD32 );
  420.    poke( lSharedMemory+4, WM_CHAR, UWORD32 );
  421.    poke( lSharedMemory+8, pParam1, UWORD32 );
  422.    poke( lSharedMemory+12, pParam2, UWORD32 );
  423.  
  424.    // send message to window accelerator in case it wants to translate
  425.    WinSendMsg(gKPFocusWindow,WM_TRANSLATEACCEL,lSharedMemory,0);
  426.    // send translated message to the window
  427.    WinSendMsg(peek(lSharedMemory,UWORD32),peek(lSharedMemory+4,UWORD32),
  428.               peek(lSharedMemory+8,UWORD32),peek(lSharedMemory+12,UWORD32));
  429. }
  430.  
  431.